clear all
load env24_12.mat

SNR = 1:6;

for snr = 1:length(SNR)
    
    cont = 0;
    rand('state',0);
	randn('state',0);
    
    tx = [];
    rxCI = [];
    rxMLD = [];
    
    diferentes(snr) = 0;
    
    while (cont < 1e4)
    
        % Mensagem
        u = randint(1, k);
    
        % Palavra Binaria Codificada
        cw = abs(mod((u * G), 2));
        
        % Acumula mensgens transmitidas
        tx = [tx cw];

        % Modulação BPSK
        x = 2*cw - 1;

        % Ruido AWGN
        y = awgn(x, SNR(snr));
        
        %------------------------------------------------------------------
        % CI
        %------------------------------------------------------------------
        % Inicia com primeiro elemento de select_list
        line = 1;
        
        % Ordena itens dos mais confiáveis para os menos confiáveis
        [val, ordem] = sort(abs(y),'descend');
        
        % Determinante de Gparcial deve ser ímpar
        detGp = 0;
        while (mod(detGp, 2) == 0)
        
            for i = 1:k
                k_bits(i) = ordem(1, select_list(line,i));
            end
            
    
            for i = 1:k
                msg0(1, i) = y(1,k_bits(1,i))>0;
                Gparcial(:,i) = G(:,k_bits(1,i));
            end
            
            detGp = det(Gparcial);
            line = line + 1;
            
            if (line > 41)
                disp('Impossível gerar matriz Gnova!');
            end
        end
        
        % Calcula Gnova
        Gnova = round(det(Gparcial)*inv(Gparcial)*G);
        [r, c] = size(Gnova);

        % Gnova em mod-2
        for row = 1:r
            for col = 1:c
                while (Gnova(row,col) < 0)
                    Gnova(row,col) = Gnova(row,col) + 2;
                end
                while (Gnova(row,col) > 1)
                    Gnova(row,col) = Gnova(row,col) - 2;
                end
            end
        end
        
        % Primeira palavra candidata
        cw_temp = msg0 * Gnova;

        for i = 1:c
            while (cw_temp(1,i) > 1)
                cw_temp(1,i) = cw_temp(1,i) - 2;
            end
        end
        
        cw_candidatas(1,:) = cw_temp;
        dEuc(1) = sum((y - (2*cw_temp-1)).^2);
        
        masc = [zeros(1,k-1) 1];
        
        % As outras candidatas são permutações de cada bit da palavra
        % original
        for j = 2:(n+1)
            msg_temp = xor(msg0, masc);
            cw_temp = msg_temp * Gnova;

            for i = 1:c
                while (cw_temp(1,i) > 1)
                    cw_temp(1,i) = cw_temp(1,i) - 2;
                end
            end
        
            cw_candidatas(j,:) = cw_temp;
            dEuc(j) = sum((y - (2*cw_temp-1)).^2);
            
            masc = transp(circshift(transp(masc),-1));
        end
        
        % Escolhe-se a palavra com menor distancia encludiana de y
        [val, pos] = min(dEuc);
        
        decodCI = cw_candidatas(pos,:);
    
        % Acumula mensagens recebidas
        rxCI = [rxCI decodCI];
        
        
        %------------------------------------------------------------------
        % MLD
        %------------------------------------------------------------------
        % Procura MLD
        [r,c] = size(palavrasCod);

        % Calcula-se uma MLD inicial, para o primeiro elemento de palavrasCod
        pc_elem = palavrasCod(1,:);
        %mld = sum(xor(pc_elem, d));
        mld = sum((y - (2*pc_elem-1)).^2);

        % A palavra decodificada assume esse elemento inicial
        decodMLD = pc_elem;

        for i = 2:r
            % Para cada linha de palavrasCod, calcula-se a distancia
            % Euclidiana
            pc_elem = palavrasCod(i,:);
            dEucMLD = sum((y - (2*pc_elem-1)).^2);
    
            % Se a dHam calculada for menor do que a MLD calculada, seleciona-se a
            % palavra codigo correspondente como palavra decodificada
            if (dEucMLD < mld)
                decodMLD = pc_elem;
                mld = dEucMLD;
            end
        end
        
        
        if (sum(xor (decodCI, decodMLD>0)) ~= 0)
            diferentes(snr) = diferentes(snr) + 1;
        end
      
        
        
        % Acumula mensagens recebidas
        rxMLD = [rxMLD decodMLD>0];

        cont = cont + 1;
    end
    
    ber24_12ci(snr) = sum(xor(tx, rxCI))/(cont*n)
    ber24_12mld(snr) = sum(xor(tx, rxMLD))/(cont*n)
end

save simul24_12.mat ber24_12ci ber24_12mld SNR

% Resultados
figure(2);
semilogy(SNR, ber24_12mld,'b');
hold all;
semilogy(SNR, ber24_12ci,'r');
hold off;
title('Golay code (24,12)');
xlabel('SNR (dB)');
ylabel('BER');
legend('MLD','CI');
axis([min(SNR) max(SNR) 1e-6 1e-1])
grid on;